﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.UI.WebControls;
using MIAP.DataAccess.Interfaces;
using MIAP.Entidades;
using MIAP.Entidades.Enums;

namespace MIAP.Negocio
{
    /// <summary>
    /// Clase que almacena las operaciones comunes al sistema.
    /// </summary>
    public class ComunesNegocio
    {
        #region Campos

        /// <summary>
        /// Instancia para el acceso a datos de Actualización de Versión Válida.
        /// </summary>
        private readonly IActualizaVersionDao daoActualizacion;

        /// <summary>
        /// Instancia para el acceso a datos de Actualización de Versión Válida.
        /// </summary>
        private readonly ICargasArchivosDao daoCargaArchivos;

        #endregion

        /// <summary>
        /// Valor del Item Todos
        /// </summary>
        public string ValorTodos = "1000";

        #region Constructor

        /// <summary>
        /// Inicializa una instancia de <see cref="ComunesNegocio"/>
        /// </summary>
        public ComunesNegocio()
        {
            this.daoActualizacion = DataAccessFactory.Instance.CreateActualizacionVersionDao();
            this.daoCargaArchivos = DataAccessFactory.Instance.CreateCargasArchivosDao();
        }

        #endregion
        /// <summary>
        /// Obtiene una lista de estatus.
        /// </summary>
        /// <returns></returns>
        public List<CatalogoInfo> GetEstatus()
        {
            var listaEstatus = new List<CatalogoInfo>
                {
                    new CatalogoInfo
                        {
                            IdItem = (int) Estatus.Activo,Descripcion = Enum.GetName(typeof (Estatus), Estatus.Activo)
                        },
                    new CatalogoInfo
                        {
                            IdItem = (int) Estatus.Inactivo,Descripcion = Enum.GetName(typeof (Estatus), Estatus.Inactivo)
                        }
                };

            return listaEstatus;
        }

        /// <summary>
        /// Obtiene una lista de item con los estados de Si y No.
        /// </summary>
        /// <returns></returns>
        public List<CatalogoInfo> GetSiNo()
        {
            var listaSiNo = new List<CatalogoInfo>
                {
                    new CatalogoInfo {IdItem = (int) SiNo.Si, Descripcion = Enum.GetName(typeof (SiNo), SiNo.Si)},
                    new CatalogoInfo {IdItem = (int) SiNo.No, Descripcion = Enum.GetName(typeof (SiNo), SiNo.No)}
                };

            return listaSiNo;
        }

        /// <summary>
        /// Obtiene una lista de meses.
        /// </summary>
        /// <returns></returns>
        public List<CatalogoInfo> GetMeses()
        {
            var listaMeses = new List<CatalogoInfo>
                {
                    new CatalogoInfo
                        {
                            IdItem = (int) Meses.Enero, Descripcion = Enum.GetName(typeof (Meses), Meses.Enero)
                        },
                    new CatalogoInfo
                        {
                            IdItem = (int) Meses.Febrero, Descripcion = Enum.GetName(typeof (Meses), Meses.Febrero)
                        },
                        new CatalogoInfo
                        {
                            IdItem = (int) Meses.Marzo, Descripcion = Enum.GetName(typeof (Meses), Meses.Marzo)
                        },
                        new CatalogoInfo
                        {
                            IdItem = (int) Meses.Abril, Descripcion = Enum.GetName(typeof (Meses), Meses.Abril)
                        },
                        new CatalogoInfo
                        {
                            IdItem = (int) Meses.Mayo, Descripcion = Enum.GetName(typeof (Meses), Meses.Mayo)
                        },
                        new CatalogoInfo
                        {
                            IdItem = (int) Meses.Junio, Descripcion = Enum.GetName(typeof (Meses), Meses.Junio)
                        },
                        new CatalogoInfo
                        {
                            IdItem = (int) Meses.Julio, Descripcion = Enum.GetName(typeof (Meses), Meses.Julio)
                        },
                        new CatalogoInfo
                        {
                            IdItem = (int) Meses.Agosto, Descripcion = Enum.GetName(typeof (Meses), Meses.Agosto)
                        },
                        new CatalogoInfo
                        {
                            IdItem = (int) Meses.Septiembre, Descripcion = Enum.GetName(typeof (Meses), Meses.Septiembre)
                        },
                        new CatalogoInfo
                        {
                            IdItem = (int) Meses.Octubre, Descripcion = Enum.GetName(typeof (Meses), Meses.Octubre)
                        },
                        new CatalogoInfo
                        {
                            IdItem = (int) Meses.Noviembre, Descripcion = Enum.GetName(typeof (Meses), Meses.Noviembre)
                        },
                        new CatalogoInfo
                        {
                            IdItem = (int) Meses.Diciembre, Descripcion = Enum.GetName(typeof (Meses), Meses.Diciembre)
                        }
                };

            return listaMeses;
        }

        /// <summary>
        /// Obtiene una lista de 10 años a partir del actual.
        /// </summary>
        /// <returns>Lista con los años.</returns>
        public List<CatalogoInfo> GetAños()
        {
            List<CatalogoInfo> listaAños = new List<CatalogoInfo>();

            int año = DateTime.Now.Year;

            for (int i = 2; i >= 1; i--)
            {
                listaAños.Add(new CatalogoInfo()
                {
                    IdItem = año - i,
                    Descripcion = (año - i).ToString()
                });
            }

            listaAños.Add(new CatalogoInfo { IdItem = año, Descripcion = año.ToString() });

            for (int i = 1; i < 10; i++)
            {
                listaAños.Add(new CatalogoInfo()
                {
                    IdItem = año + i,
                    Descripcion = (año + i).ToString()
                });
            }

            return listaAños;
        }

        /// <summary>
        /// Coloca el item de seleccionar en el drop down 
        /// </summary>
        /// <param name="mensajeSeleccionar">mensaja a colocar el el drop</param>
        /// <param name="downList">dorp donde se colocara el mensaje</param>
        public void SetSeleccionar(string mensajeSeleccionar, DropDownList downList)
        {
            downList.Items.Insert(0, new ListItem(mensajeSeleccionar, "-1"));
        }

        /// <summary>
        /// Coloca el item de Todos en el drop down 
        /// </summary>
        /// <param name="mensajeTodos">mensaja a colocar el el drop</param>
        /// <param name="downList">dorp donde se colocara el mensaje</param>
        public void SetTodos(string mensajeTodos, DropDownList downList)
        {
            downList.Items.Insert(0, new ListItem(mensajeTodos, ValorTodos));
        }

        /// <summary>
        /// metodo que selecciona un elemento en el drop de proyectos, si no existe lo agrega
        /// </summary>
        /// <param name="dropDownList"></param>
        /// <param name="proySeleccionar"></param>
        public void SelectProyectoItem(DropDownList dropDownList, ProyectoInfo proySeleccionar)
        {
            if (dropDownList == null || proySeleccionar == null || dropDownList.Items.Count == 0) return;
            var item = new ListItem(proySeleccionar.NombreProyecto, proySeleccionar.IDProyecto.ToString());

            if (!dropDownList.Items.Contains(item))
            {
                dropDownList.Items.Insert(dropDownList.Items.Count, item);
            }

            dropDownList.SelectedValue = item.Value;
        }

        /// <summary>
        /// Seleccionamos el archivo de un dropdown, si no existe se agrega
        /// </summary>
        /// <param name="dropDownList"></param>
        /// <param name="archivoSeleccionar"></param>
        public void SelectArchivoItem(DropDownList dropDownList, ArchivoInfo archivoSeleccionar)
        {
            if (dropDownList == null || archivoSeleccionar == null) return;
            var item = new ListItem(archivoSeleccionar.NombreArchivo, archivoSeleccionar.IdentificadorArchivo.ToString());

            if (!dropDownList.Items.Contains(item))
            {
                dropDownList.Items.Insert(dropDownList.Items.Count, item);
            }

            dropDownList.SelectedValue = item.Value;
        }

        /// <summary>
        /// Filtra la lista de archivos por los proyectos en los cuales el usuario tiene permiso y estos estan activos
        /// </summary>
        /// <param name="listaArchivos">Lista de archivos a filtrar</param>
        /// <param name="listaIdProyectos">Id de proyectos permitidos</param>
        /// <returns></returns>
        public List<ArchivoInfo> FiltrarArchivosProyecto(List<ArchivoInfo> listaArchivos, List<int> listaIdProyectos)
        {
            var activo = Enum.GetName(typeof(Estatus), Estatus.Activo).Trim().ToUpper();
            var resultado = from archivo in listaArchivos
                            where listaIdProyectos.Contains(archivo.Proyecto.IDProyecto) && archivo.Proyecto.Estatus.Trim().ToUpper() == activo
                            select archivo;

            return resultado.ToList();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="listArchivos"></param>
        /// <returns></returns>
        public static List<T> GetArchivoWithLastProcess<T>(List<T> listArchivos) where T : ListaInfo
        {
            DateTime fechaProceso = DateTime.MinValue;
            int idArchivo = default(int);
            int idProyecto = default(int);

            ListaInfo archivoRecarga = new ListaInfo();

            List<T> listArchivosRecargables = new List<T>();

            List<T> listAuxiliarArchivo = new List<T>();

            // Recorrer los archivos obtenidos de la consulta "GetArchivosRecarga".
            foreach (ListaInfo archivo in listArchivos)
            {
                // Preguntar si el archivo es versionable
                if (archivo.Versionable)
                {
                    // Obtener todas las cargas y recargas de esa versión de archivo.
                    listAuxiliarArchivo = listArchivos.Where(p => p.IdArchivo.Value == archivo.IdArchivo.Value && p.IdProyecto.Value == archivo.IdProyecto.Value && p.Version == archivo.Version).ToList();

                    int cantidadArchivos = -1;

                    fechaProceso = DateTime.MinValue;

                    // Obtener el archivo con el último proceso.
                    foreach (ListaInfo archivoAxiliar in listAuxiliarArchivo)
                    {
                        cantidadArchivos++;

                        if (archivoAxiliar.FechaProceso > fechaProceso)
                        {
                            idArchivo = archivoAxiliar.IdArchivo.Value;
                            idProyecto = archivoAxiliar.IdProyecto.Value;
                            fechaProceso = archivoAxiliar.FechaProceso;

                            archivoRecarga = listAuxiliarArchivo[cantidadArchivos];
                        }
                    }

                    ListaInfo archivoExistente = listArchivosRecargables.Where(p => p.IdArchivo.Value == archivoRecarga.IdArchivo.Value && p.IdProyecto.Value == archivoRecarga.IdProyecto.Value && p.FechaProceso == archivoRecarga.FechaProceso).SingleOrDefault();

                    if (archivoExistente == null)
                    {
                        listArchivosRecargables.Add((T)archivoRecarga);
                    }
                }
                else
                {
                    // Obtener todas las cargas y recargas de un archivo no versionable.
                    listAuxiliarArchivo = listArchivos.Where(p => p.IdArchivo.Value == archivo.IdArchivo.Value && p.IdProyecto.Value == archivo.IdProyecto.Value).ToList();

                    // Obtener el archivo con el último proceso.
                    foreach (ListaInfo archivoAxiliar in listAuxiliarArchivo)
                    {
                        if (archivoAxiliar.FechaProceso > fechaProceso)
                        {
                            idArchivo = archivoAxiliar.IdArchivo.Value;
                            idProyecto = archivoAxiliar.IdProyecto.Value;
                            fechaProceso = archivoAxiliar.FechaProceso;

                            archivoRecarga = listAuxiliarArchivo.Where(p => p.IdArchivo.Value == idArchivo && p.IdProyecto.Value == idProyecto && p.FechaProceso == fechaProceso).First();
                        }
                    }

                    ListaInfo archivoExistente = listArchivosRecargables.Where(p => p.IdArchivo.Value == archivoRecarga.IdArchivo.Value && p.IdProyecto.Value == archivoRecarga.IdProyecto.Value && p.FechaProceso == archivoRecarga.FechaProceso).SingleOrDefault();

                    if (archivoExistente == null)
                    {
                        listArchivosRecargables.Add((T)archivoRecarga);
                    }
                }
            }

            return listArchivosRecargables;
        }

        /// <summary>
        /// Obtiene el autorizador de la recarga del archivo.
        /// </summary>
        /// <param name="listArchivos">Lista de archivos de los cuales se obtendrá el autorizador.</param>
        /// <returns>Lista de autorizadores.</returns>
        public List<EjecutorInfo> GetAutorizador(List<CatalogoInfo> listArchivos)
        {
            return this.daoActualizacion.GetAutorizador(listArchivos).ToList();
        }

        /// <summary>
        /// Obtiene el nombre del versionador de la carga o recarga del archivo.
        /// </summary>
        /// <param name="listArchivos">Lista de archivos versionables.</param>
        /// <returns>Lista de ids de archivos y sus respectivos versionadores.</returns>
        public IList<CatalogoInfo> GetNombreVersionador(List<CatalogoInfo> listArchivos)
        {
            return this.daoActualizacion.GetNombreVersionador(listArchivos).ToList();
        }

        /// <summary>
        /// si existio algun error detectado por nuestra aplicación en la ejecucion de proyectos o 
        /// carga de archivos este se marcará con estatus de error
        /// </summary>
        /// <param name="idBitGeneral">Id del registro que fue iniciado</param>
        /// <param name="usuario">usuario quien realiza el proceso</param>
        public void SetProcesoError(int idBitGeneral, string usuario)
        {
             this.daoCargaArchivos.SetProcesoError(idBitGeneral,usuario);
        }
    }
}
